import { AuthUtil } from '@/core';
import {
	DrtabActionType,
	EditView3ActionType,
	EditFormActionType,
	IEditView3Ability,
	IParam,
	IViewActionResult,
} from '@/core/interface';
import { IEditView3Controller } from '@/core/interface/view/controller';
import { IEditView3ControllerParams } from '@/core/interface/view/controller-params';
import { IEditView3Store } from '@/core/interface/view/store';
import {
	IDrtabAbility,
	IEditFormAbility,
} from '@/core/interface/widgets/ability';
import { DEViewController } from './de-view-controller';

/**
 * 编辑视图3控制器
 *
 * @export
 * @class EditView3Controller
 * @extends {DEViewController}
 */
export class EditView3Controller
	extends DEViewController<
		EditView3ActionType,
		IEditView3Store,
		IEditView3Ability
	>
	implements IEditView3Controller<IEditView3Store, IEditView3Ability>
{
	/**
	 * 处理视图初始化
	 *
	 * @protected
	 * @param {IEditView3ControllerParams<EditView3ActionType, IEditView3Ability>} params
	 * @memberof EditView3Controller
	 */
	protected processViewInit(
		params: IEditView3ControllerParams<EditView3ActionType, IEditView3Ability>
	) {
		super.processViewInit(params);
		Object.assign(this.store, { dataInfo: '', selection: {} });
	}

	/**
	 * @description 获取表单部件能力
	 * @protected
	 * @return {*}  {(IEditFormAbility | undefined)}
	 * @memberof EditView3Controller
	 */
	protected getFormAbility(): IEditFormAbility | undefined {
		const form = this.model.ctrls.find(
			(ctrl: IParam) => ctrl.controlType === 'FORM'
		);
		if (form) {
			return this.getSubAbility<IEditFormAbility>(form.name);
		}
	}

	/**
	 * @description 获取drbar部件能力
	 * @protected
	 * @return {*}  {(IDrtabAbility | undefined)}
	 * @memberof EditView3Controller
	 */
	protected getDrtabAbility(): IDrtabAbility | undefined {
		const drtab = this.model.ctrls.find(
			(ctrl: IParam) => ctrl.controlType === 'DRTAB'
		);
		if (drtab) {
			return this.getSubAbility<IDrtabAbility>(drtab.name);
		}
	}

	/**
	 * 视图加载
	 *
	 * @param {IParam} [opts={}]
	 * @return {*}
	 * @memberof EditView3Controller
	 */
	public viewMounted(opts: IParam = {}) {
		super.viewMounted(opts);
		if (this.model.useDefaultLayout) {
			if (!this.isLoadDefault) {
				this.isLoadDefault = true;
				return;
			}
			this.load();
		} else {
			this.initLayout().then(() => {
				this.load();
			});
		}
	}

	/**
	 * 视图加载
	 *
	 * @param {IParam} [args]
	 * @return {*}  {Promise<IViewActionResult>}
	 * @memberof EditView3Controller
	 */
	public load(args?: IParam): Promise<IViewActionResult> {
		const form = this.getFormAbility();
		if (form) {
			let action: 'loadDraft' | 'load' = 'loadDraft';
			if (
				this.model.entityCodeName &&
				this.store.context[this.model.entityCodeName.toLowerCase()]
			) {
				action = 'load';
			}
			return form[action](Object.assign(this.store.viewParams, args));
		} else {
			return Promise.reject({
				ok: false,
				data: null,
				rowData: { status: 500 },
			});
		}
	}

	/**
	 * 处理部件行为
	 *
	 * @param {string} name 部件标识
	 * @param {EditFormActionType | DrtabActionType} action 部件行为
	 * @param {IParam[]} data 行为数据
	 * @memberof EditView3Controller
	 */
	public handleCtrlAction(
		name: string,
		action: EditFormActionType | DrtabActionType,
		data: IParam[]
	): void {
		super.handleCtrlAction(name, action, data);
		const form = this.getFormAbility();
		const drtab = this.getDrtabAbility();
		if (form && name === form.name) {
			this.handleFormCtrlAction(action as EditFormActionType, data);
			return;
		}
		if (drtab && name === drtab.name) {
			this.handleDrtabAction(action as DrtabActionType, data);
			return;
		}
	}

	/**
	 * @description 处理表单部件行为
	 * @template T
	 * @param {(T | EditFormActionType)} action
	 * @param {IParam[]} data
	 * @memberof EditView3Controller
	 */
	protected handleFormCtrlAction<T>(
		action: T | EditFormActionType,
		data: IParam[]
	) {
		if (action === 'load' || action === 'loadDraft') {
			this.handleFormLoad(data);
		}
		if (action === 'save') {
			this.handleFormSave(data);
		}
		if (action === 'remove') {
			this.handleFormRemove(data);
		}
	}

	/**
	 * 处理drtab部件行为
	 * @param {(DrtabActionType)} action
	 * @param {IParam[]} data
	 * @memberof EditView3Controller
	 */
	protected handleDrtabAction(action: DrtabActionType, data: IParam[]) {
		if (Object.is(action, 'selectionChange') && data.length > 0) {
			this.store.selection = data[0];
			this.emit('selectionChange', data);
		}
	}

	/**
	 * 处理drtab数据
	 *
	 * @protected
	 * @param {IParam[]} data
	 * @memberof EditView3Controller
	 */
	protected handleDrtabData(data: IParam[]) {
		const drtab = this.getDrtabAbility();
		if (drtab) {
			const arg = data[0];
			if (this.model.entityCodeName) {
				Object.assign(this.store.context, {
					srfparentkey: this.model.entityCodeName,
				});
				Object.assign(this.store.viewParams, {
					srfparentkey: this.model.entityCodeName,
				});
			}
			if (arg.srfkey) {
				Object.assign(this.store.context, { srfparentdename: arg.srfkey });
				Object.assign(this.store.viewParams, { srfparentdename: arg.srfkey });
			}
			drtab.handleFormChange(arg);
		}
	}

	/**
	 * 处理表单加载完成
	 *
	 * @param {IParam[]} data 表单数据
	 * @memberof EditView3Controller
	 */
	public async handleFormLoad(data: IParam[]) {
		await this.handleFormData(data);
		this.handleDrtabData(data);
		this.emit('viewDataLoaded', data);
	}

	/**
	 * 处理表单保存
	 *
	 * @param {IParam[]} data
	 * @memberof EditView3Controller
	 */
	protected async handleFormSave(data: IParam[]) {
		await this.handleFormData(data);
		this.handleDrtabData(data);
		this.emit('viewDataChange', data);
		this.emit('viewDataSave', data);
	}

	/**
	 * 处理表单删除
	 *
	 * @param {IParam[]} data
	 * @memberof EditView3Controller
	 */
	protected handleFormRemove(data: IParam[]) {
		this.emit('viewDataChange', data);
	}

	/**
	 * 处理表单数据
	 *
	 * @param {IParam[]} data
	 * @memberof EditView2Controller
	 */
	protected async handleFormData(data: IParam[]) {
		const arg = data[0];
		this.store.dataInfo = Object.is(arg.srfuf, '1')
			? this.model.majorPSAppDEField
				? arg[this.model.majorPSAppDEField.toLowerCase()]
				: arg.srfmajortext
			: App.ts('view.editview.newbuild', '新建');
		AuthUtil.calcToolbarItemState(
			Object.is(arg.srfuf, '0'),
			this.store.toolbarCtrls
		);
		await this.calcToolbarItemAuthState(arg);
	}
}
